package project;

import java.awt.Point;

public class Validity {
	
	static private boolean isValid(WallMove move, GameState state) {
		
		if (state.gameOver() != GameState.GAMENOTOVER)
			return false;
		if (move.getX() < 0 || move.getX() > 7)
			return false;
		if (move.getY() < 0 || move.getY() > 7)
			return false;
		if (state.players[move.getPlayer()].getWallCount() == 0)
			return false;
		
		int i;
		boolean ans;
		int x = move.getX();
		int y = move.getY();
		
		if (move.isHorizontal) {
			for (i = 0; i < 3; i++)
				if (state.grid[x * 2 + i][y * 2 + 1] != GameState.EMPTY)
					return false;
			for (i = 0; i < 3; i++)
				state.grid[x * 2 + i][y * 2 + 1] = GameState.HORIZONTAL;
		} else {
			for (i = 0; i < 3; i++)
				if (state.grid[x * 2 + 1][y * 2 + i] != GameState.EMPTY)
					return false;
			for (i = 0; i < 3; i++)
				state.grid[x * 2 + 1][y * 2 + i] = GameState.VERTICAL;
		}
		
		ans = (Astar.findDist(0, state) != -1 && Astar.findDist(1, state) != -1);
		
		if (move.isHorizontal) {
			for (i = 0; i < 3; i++)
				state.grid[x * 2 + i][y * 2 + 1] = GameState.EMPTY;
		} else {
			for (i = 0; i < 3; i++)
				state.grid[x * 2 + 1][y * 2 + i] = GameState.EMPTY;
		}
		
		return ans;
	}

	static private boolean isValid(PawnMove move, GameState state) {
		
		if (state.gameOver() != GameState.GAMENOTOVER)
			return false;
		
		PlayerState[] players = state.getPlayers();
		Point currentPlayer = players[move.player].getCoords();
		Point otherPlayer = players[1-move.player].getCoords();
		
		int manhattan = Math.abs(currentPlayer.x - move.getX())
					  + Math.abs(currentPlayer.y - move.getY());
		
		if (move.getX() < 0 || move.getX() > 8 || 
			move.getY() < 0 || move.getY() > 8) {
			return false;
		}
		
		if (move.getX() == otherPlayer.x && move.getY() == otherPlayer.y) {
			return false;
		}
		
		if (manhattan == 2) {
			//Check that the opponent is adjacent
			if (Math.abs(currentPlayer.x-otherPlayer.x) 
			  + Math.abs(currentPlayer.y-otherPlayer.y) != 1) {
				return false;
			}
			
			//Check that there is no wall between us and the opponent
			if (!notWallBetween(state, currentPlayer, otherPlayer)) {
				return false;
			}
			
			//Check if a straight move is possible
			Point straight = new Point(otherPlayer.x*2-currentPlayer.x, otherPlayer.y*2-currentPlayer.y);
			boolean validStraight = notWallBetween(state, straight, otherPlayer);
			
			if (move.getX() == currentPlayer.x || move.getY() == currentPlayer.y) {
				return notWallBetween(state, move.getCoords(), otherPlayer);
			} else if (!validStraight) {
				return notWallBetween(state, move.getCoords(), otherPlayer);
			} else {
				return false;
			}
			
		} else if (manhattan == 1) {
			return notWallBetween(state, currentPlayer, move.getCoords());
		} else {
			return false;
		}
	}
	
	private static boolean notWallBetween(GameState game, Point from, Point to) {
		if (to.x < 0 || to.x > 8 || to.y < 0 || to.y > 8)
			return false;
		if (from.x < 0 || from.x > 8 || from.y < 0 || from.y > 8)
			return false;
		if (Math.abs(from.x-to.x)+Math.abs(from.y-to.y) != 1) {
			return false;
		}
		return game.getGrid()[(from.x*2+to.x*2)/2][(from.y*2+to.y*2)/2] == GameState.EMPTY;
	}

	public static boolean isValid(Move move, GameState game) {
		if (move instanceof WallMove) {
			return Validity.isValid((WallMove)move, game);
		} else if (move instanceof PawnMove) {
			return Validity.isValid((PawnMove)move, game);
		} else {
			return false;
		}
	}
}